package tmts;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

import models.Skater;
import tmts.commands.Add;
import tmts.commands.Command;
import tmts.commands.Reset;
import tmts.commands.SetSpeed;
import tmts.commands.Simulatie;
import tmts.commands.SimulatieDrie;
import tmts.commands.SimulatieTwee;
import tmts.commands.Start;
import tmts.commands.Stop;
import tmts.helpers.InputParser;

public class Server
{

    public final static boolean PRINT_DEBUG = false;
    public static boolean raceRunning;
    public static ArrayList<Skater> skaters = new ArrayList<Skater>();
    public static int simulateSpeed = 1;
    static DatabaseHandler db_handler = new DatabaseHandler();

    protected HashMap<String, Command> parsers = new HashMap<String, Command>();
    protected InputParser inputParser = new InputParser();
    protected Scanner commandLine = new Scanner(System.in);

    public static void main(String[] args)
    {
        new Server();
    }

    public static void debug(String debug)
    {
        if (PRINT_DEBUG)
        {
            Timestamp p = new Timestamp(System.currentTimeMillis());
            String time = new SimpleDateFormat("kk:mm:ss").format(p);
            System.out.println(time + ": " + debug);
        }
    }

    public Server()
    {
        Server.debug("Server started");

        initializeCommand();
        initializeBroadcastService();
        clearRemoteDatabase();
        printUsage();

        processInput();
    }

    public void printUsage()
    {
        System.out.println("Possible commands: start <raceId>, stop, add <skaterfile>, reset, setSpeed <speed>");
    }

    public void clearRemoteDatabase()
    {
        Server.db_handler.emptyDatabase("skater_lines");
    }

    private void processInput()
    {
        String line = null;
        while ((line = commandLine.nextLine()) != null)
        {
            debug("INPUT " + line);

            String[] command = inputParser.parse(line);
            if (command.length > 0)
            {
                Command c = parsers.get(command[0].toLowerCase());
                if (c != null)
                {
                    System.out.println(c.execute(command));
                } else
                {
                    System.out.println("Command not found");
                }
            } else
            {
                printUsage();
            }
        }
    }

    public void addSkater(Skater s)
    {
        skaters.add(s);
        System.out.println("Skater added");
    }

    public void setSimulateSpeed(int speed)
    {
        Server.simulateSpeed = speed;
    }

    public void resetRace()
    {
        skaters.clear();
        Server.raceRunning = false;
    }

    public void initializeBroadcastService()
    {
        Thread broadCastService = new BroadCastService();
        broadCastService.start();
    }

    public void initializeCommand()
    {
        addParser(new Add(this));
        addParser(new Reset(this));
        addParser(new SetSpeed(this));
        addParser(new Start(this));
        addParser(new Stop(this));
        addParser(new Simulatie(this));
        addParser(new SimulatieTwee(this));
        addParser(new SimulatieDrie(this));
    }

    private void addParser(Command cmd)
    {
        parsers.put(cmd.getActionString(), cmd);
    }

    public void startRace(int raceId)
    {
        clearRemoteDatabase();
        if (skaters.size() > 0)
        {
            raceRunning = true;
            db_handler.startRace(raceId, skaters.get(0).getTotalDistance(), skaters);

            for (Skater skater : Server.skaters)
            {
                skater.setRaceId(raceId);
                skater.start();
            }
        } else
        {
            System.out.println("No skaters in the race, add some skaters first");
        }
    }

    public void stopRace()
    {
        if (!Server.raceRunning)
            System.out.println("Race isn't running");
        else
        {
            Server.raceRunning = false;
            skaters.clear();
        }
    }

}
